/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.seari.ibpPanleMidware.main;

import com.ghgande.j2mod.modbus.io.ModbusTCPTransaction;
import com.ghgande.j2mod.modbus.msg.ReadMultipleRegistersRequest;
import com.ghgande.j2mod.modbus.msg.ReadMultipleRegistersResponse;
import com.ghgande.j2mod.modbus.net.TCPMasterConnection;
import com.ghgande.j2mod.modbus.procimg.Register;
import com.seari.commonutils.redis.JedisUtilProxy;
import com.seari.commonutils.redis.ex.JedisNotInitializeException;
import com.seari.ibpPanleMidware.bean.StationConfig;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

/**
 *
 * @author Rainbow
 */
@Component
@Scope("prototype")
public class IbpDataWorker implements Runnable
{
    public boolean terminate = false;
    private String group;
    private List<StationConfig> targetStationConfigs = new ArrayList<>();
    
    @Override
    public void run()
    {
        Jedis jedis = null;
        try
        {
            jedis = JedisUtilProxy.getJedis();
            while (!terminate)
            {
                if (jedis.isConnected())
                {
                    for (StationConfig targetStationConfig : targetStationConfigs)
                    {
                        int data[] = readRegister(targetStationConfig);
                        updateRedisData(jedis,data,targetStationConfig);
                    }
                }else {
                    //JEDIS连接失败时将当前连接回收至连接池，并获取新连接
                    JedisUtilProxy.close(jedis);
                    JedisUtilProxy.getJedisPool().returnBrokenResource(jedis);
                    jedis = JedisUtilProxy.getJedis();
                }
                TimeUnit.SECONDS.sleep(2);
            }
        } catch (Exception e)
        {
            e.printStackTrace();
        }finally{
            JedisUtilProxy.close(jedis);
            //终止标志不为真时，认为此线程非正常退出，进行线程重启
            if(!terminate)
            {
                try
                {
                        TimeUnit.SECONDS.sleep(2);
                        Thread.currentThread().interrupt();
                } catch (Exception e2)
                {
                        // TODO: handle exception
                }
                new Thread(this).start();
            }
        }
    }
    
    private void updateRedisData(Jedis jedis,int[] data,StationConfig stationConfig) throws JedisNotInitializeException
    {
        try
        {
            jedis.hset(stationConfig.getDataTableName(), stationConfig.getStationId() + "", data[0] + "");
            jedis.hset(stationConfig.getDataTableName(), stationConfig.getStationId() + "_FAS", data[1] + "");
        } catch (Exception e)
        {
            //异常处理时重新获取JEDIS实例，防止异常后JEDIS未归还至连接池
            e.printStackTrace();
            JedisUtilProxy.close(jedis);
            jedis = JedisUtilProxy.getJedis();
        }
    }
    
    private int[] readRegister(StationConfig stationConfig)
    {
        int data[] = new int[]{-1,-1};
        TCPMasterConnection con = null;
        String ipStrs[] = stationConfig.getDataIpListArray();
        for (String ipStr : ipStrs)
        {
            try 
            {
                InetAddress addr = InetAddress.getByName(ipStr);
                /*TCPMasterConnection */
                con = new TCPMasterConnection(addr);
                con.setPort(502);
                con.connect();
                ReadMultipleRegistersRequest req = new ReadMultipleRegistersRequest(stationConfig.getDataAddress(),1);
                req.setUnitID(1);
                ModbusTCPTransaction trans = new ModbusTCPTransaction(con);
                trans.setRequest(req);
                trans.execute();
                ReadMultipleRegistersResponse res = (ReadMultipleRegistersResponse) trans.getResponse();
                //ReadMultipleRegistersResponse res = (ReadMultipleRegistersResponse) con.getModbusTransport().readResponse();
                Register[] registers = res.getRegisters();
                data[0] = registers[0].getValue();
                data[1] = getExtendValue(stationConfig, con);
                break; //读取成功时直接BREAK出循环
            } catch (Exception e) {
                //读取异常的时候以-1返回
                System.out.println("读取异常的时候以-1返回------>ip"+ipStr);
            }finally{
                if(con!=null)
                {
                    con.close();
                }
            }
        }
        return data;
    }
    
    private int getExtendValue(StationConfig stationConfig,TCPMasterConnection con)
    {
        int data = -1;
        try
        {
            ReadMultipleRegistersRequest req = new ReadMultipleRegistersRequest(Integer.parseInt(stationConfig.getDataExtend1()),1);
            req.setUnitID(1);
            ModbusTCPTransaction trans = new ModbusTCPTransaction(con);
            trans.setRequest(req);
            trans.execute();
            ReadMultipleRegistersResponse res = (ReadMultipleRegistersResponse) trans.getResponse();
            //ReadMultipleRegistersResponse res = (ReadMultipleRegistersResponse) con.getModbusTransport().readResponse();
            Register[] registers = res.getRegisters();
            data = registers[0].getValue();
        } catch (Exception e)
        {
            e.printStackTrace();
            System.out.println("com.seari.ibpPanleMidware.main.IbpDataWorker.getExtendValue(),return -1  " + con.getAddress().getHostAddress());
        }
        return data;
    }
    
    public void init(String group,List<StationConfig> stationConfigs)
    {
        setGroup(group);
        for (StationConfig stationConfig : stationConfigs)
        {
            if(StringUtils.isNotBlank(stationConfig.getDataGroup()) && stationConfig.getDataGroup().equals(group))
            {
                targetStationConfigs.add(stationConfig);
            }
        }
    }

    public String getGroup()
    {
        return group;
    }

    public void setGroup(String group)
    {
        this.group = group;
    }
    
    
}
